/**
 * @file rtk_work.h
 * @author LokLiang (lokliang@163.com)
 * @brief
 * @version 0.1
 * @date 2023-05-01
 *
 * @copyright Copyright (c) 2023
 *
 */

#ifndef __RTK_WORK_H__
#define __RTK_WORK_H__

#include "rtk_def.h"

#ifdef __cplusplus
extern "C"
{
#endif /* #ifdef __cplusplus */

typedef struct
{
    rtk_hdl_t hdl;
} rtk_work_q_t;

extern rtk_work_q_t *default_rtk_work_q_hdl; // 预留的一个工默认的作队列对象内存，初始值为内部默认的对象

rtk_err_t rtk_work_q_init(rtk_work_q_t *work_q_handle, // 队列句柄
                          const char *name,            // 队列名
                          void *stack_base,            // 栈内存地址
                          size_t stack_size,           // 栈大小（字节）
                          rtk_prior_t priority         // 优先级（0 为最低，CONFIG_RTK_MAX_PRIORITY 为最高。若输入为负值则表示优先级为 (CONFIG_RTK_MAX_PRIORITY + 1 + priority)）
);
rtk_err_t rtk_work_q_create(rtk_work_q_t *work_q_handle, // 队列句柄
                            const char *name,            // 队列名
                            size_t stack_size,           // 栈大小（字节）
                            rtk_prior_t priority         // 优先级（0 为最低，CONFIG_RTK_MAX_PRIORITY 为最高。若输入为负值则表示优先级为 (CONFIG_RTK_MAX_PRIORITY + 1 + priority)）
);
rtk_err_t rtk_work_q_delete(rtk_work_q_t *work_q_handle); // 删除一个工作队列的对象

rtk_err_t rtk_work_q_start(rtk_work_q_t *work_q_handle); // 启动工作队列调度（初始化或创建队列时默认已启动）
rtk_err_t rtk_work_q_stop(rtk_work_q_t *work_q_handle);  // 停止工作队列调度

bool rtk_work_q_is_valid(rtk_work_q_t *work_q_handle);      // 获取工作队列是否有效
bool rtk_work_q_delayed_state(rtk_work_q_t *work_q_handle); // 获取是否有正在延时状态的任务
bool rtk_work_q_ready_state(rtk_work_q_t *work_q_handle);   // 获取工作队列中是否有就绪的任务

typedef struct
{
    rtk_hdl_t hdl;
} rtk_work_t;

typedef void (*rtk_work_fn)(void *arg);

rtk_err_t rtk_work_create(rtk_work_t *work_handle,
                          const char *name,
                          rtk_work_fn work_route,
                          void *arg,
                          u8_t sub_prior);

void      rtk_work_delete(rtk_work_t *work_handle);  // 删除由工作队列管理的任务

bool       rtk_work_is_valid(rtk_work_t *work_handle);    // 获取任务对象是否有效
bool       rtk_work_is_pending(rtk_work_t *work_handle);  // 获取任务是否在就绪或延时的状态
rtk_tick_t rtk_work_time_remain(rtk_work_t *work_handle); // 获取任务距离下个执行的剩余时间

void rtk_work_submit(rtk_work_q_t *work_q_handle, rtk_work_t *work_handle, rtk_tick_t delay_ticks); // 使任务在指定工作队列中在指定时间后就绪
void rtk_work_resume(rtk_work_t *work_handle, rtk_tick_t delay_ticks);                              // 唤醒任务。注意需要先使用 rtk_work_submit 绑定一个 work_q_handle
void rtk_work_suspend(rtk_work_t *work_handle);                                                     // 挂起任务，任务不会被删除

void rtk_work_yield(rtk_tick_t delay_ticks); // 释放一次CPU的使用权，不调度低于当前任务优先级的任务
void rtk_work_sleep(rtk_tick_t delay_ticks); // 释放一次CPU的使用权，可调度低于当前任务优先级的任务
void rtk_work_later(rtk_tick_t delay_ticks); // 延时多少个系统节拍后再执行本任务
void rtk_work_later_until(rtk_tick_t delay_ticks);
void rtk_work_later_hmsm(size_t hours, size_t minute, size_t second, size_t milli);

rtk_work_t *rtk_get_curr_work_handle(rtk_work_q_t *work_q_handle); // 查询最近一次执行的任务

rtk_err_t rtk_work_mbox_create(rtk_work_t *work_handle); // 创建任务的邮箱
void      rtk_work_mbox_delete(rtk_work_t *work_handle); // 删除任务的邮箱

void     *rtk_work_mbox_alloc(rtk_work_t *work_handle, size_t size); // 申请一个邮件
rtk_err_t rtk_work_mbox_cancel(void *mbox);                          // 取消已申请的邮件
rtk_err_t rtk_work_mbox_submit(void *mbox);                          // 发送邮件
void     *rtk_work_mbox_take(void);                                  // 提取邮件
void     *rtk_work_mbox_peek(void);                                  // 查询邮件
void      rtk_work_mbox_clr(void);                                   // 清空任务的所有邮件

#ifdef __cplusplus
} /* extern "C" */
#endif /* #ifdef __cplusplus */

#endif
